namespace GomuLibrary.IO.DiscImage
{
    using System;
    using System.Runtime.InteropServices;
    using System.Text;

    [StructLayout(LayoutKind.Sequential, Size=0x800, Pack=1)]
    internal struct VolumeDescriptor
    {
        [MarshalAs(UnmanagedType.I1)]
        public byte Type;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=5)]
        public char[] ID;
        [MarshalAs(UnmanagedType.I1)]
        public byte Version;
        [MarshalAs(UnmanagedType.I1)]
        public byte Unused1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x20)]
        public char[] SystemID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x20)]
        public char[] VolumeID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
        public byte[] Unused2;
        [MarshalAs(UnmanagedType.U4)]
        public uint VolumeSpaceSize;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
        public byte[] Unused3;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x20)]
        public byte[] Unused4;
        [MarshalAs(UnmanagedType.I2)]
        public short VolumeSetSize;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
        public byte[] Unused5;
        [MarshalAs(UnmanagedType.I2)]
        public short VolumeSequenceNumber;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
        public byte[] Unused6;
        [MarshalAs(UnmanagedType.I2)]
        public short LogicalBlockSize;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
        public byte[] Unused7;
        [MarshalAs(UnmanagedType.U4)]
        public uint PathTableSize;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
        public byte[] Unused8;
        [MarshalAs(UnmanagedType.U4)]
        public uint TypeLPathTable;
        [MarshalAs(UnmanagedType.U4)]
        public uint OptTypeLPathTable;
        [MarshalAs(UnmanagedType.U4)]
        public uint TypeMPathTable;
        [MarshalAs(UnmanagedType.U4)]
        public uint OptTypeMPathTable;
        [MarshalAs(UnmanagedType.Struct)]
        public DirectoryRecord RootDirectoryRecord;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x80)]
        public char[] VolumeSetID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x80)]
        public char[] PublisherID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x80)]
        public char[] PreparerID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x80)]
        public char[] ApplicationID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x25)]
        public char[] CopyrightFileID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x25)]
        public char[] AbstractFileID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x25)]
        public char[] BibliographicFileID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x11)]
        public byte[] CreationDate;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x11)]
        public byte[] ModificationDate;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x11)]
        public byte[] ExpirationDate;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=0x11)]
        public byte[] EffectiveDate;
        [MarshalAs(UnmanagedType.I1)]
        public byte FileStructureVersion;
        public DateTime GetCreationDate() => 
            this.BytesToDateTime(this.CreationDate);

        public DateTime GetModificationDate() => 
            this.BytesToDateTime(this.ModificationDate);

        public DateTime GetExpirationDate() => 
            this.BytesToDateTime(this.ExpirationDate);

        public DateTime GetEffectiveDate() => 
            this.BytesToDateTime(this.EffectiveDate);

        private DateTime BytesToDateTime(byte[] date)
        {
            try
            {
                if ((date != null) && (date.Length == 0x11))
                {
                    string str = Encoding.Default.GetString(date);
                    string str2 = str.Substring(0, 4);
                    string str3 = str.Substring(4, 2);
                    string str4 = str.Substring(6, 2);
                    string str5 = str.Substring(8, 2);
                    string str6 = str.Substring(10, 2);
                    string str7 = str.Substring(12, 2);
                    return new DateTime(Convert.ToInt32(str2), Convert.ToInt32(str3), Convert.ToInt32(str4), Convert.ToInt32(str5), Convert.ToInt32(str6), Convert.ToInt32(str7));
                }
                return DateTime.MinValue;
            }
            catch (Exception)
            {
                return DateTime.MinValue;
            }
        }

        public static explicit operator VolumeInfo(VolumeDescriptor pvd)
        {
            char[] trimChars = new char[] { ' ' };
            string stdID = new string(pvd.ID);
            string sysID = new string(pvd.SystemID).Trim(trimChars).Replace("\0", string.Empty);
            string volID = new string(pvd.VolumeID).Trim(trimChars).Replace("\0", string.Empty);
            string pubID = new string(pvd.PublisherID).Trim(trimChars).Replace("\0", string.Empty);
            string prepID = new string(pvd.PreparerID).Trim(trimChars).Replace("\0", string.Empty);
            string appID = new string(pvd.ApplicationID).Trim(trimChars).Replace("\0", string.Empty);
            return new VolumeInfo((VolumeType) pvd.Type, stdID, pvd.Version, sysID, volID, (long) pvd.VolumeSpaceSize, pvd.VolumeSequenceNumber, pvd.LogicalBlockSize, pubID, prepID, appID, new string(pvd.CopyrightFileID).Trim(trimChars).Replace("\0", string.Empty), pvd.GetCreationDate(), pvd.GetModificationDate(), pvd.GetExpirationDate());
        }
    }
}

